Repository navigation
fix(shared): pooled limits weight each account by its plan size - #35427
Conversation
…13110) Fails on main: a used-up Pro 20x pooled with an unused Plus shows 50% left and a 50% Pro reset instead of about 5% left and a 95% reset. AI-assisted; verified with the tests and tools listed above.
Pooled Limits averaged members evenly, so a used-up ChatGPT Pro 20x pooled with an unused Plus showed 50% left and a +50% Pro reset. Weight pooled used percent, pace and reset shares by plan capacity: Codex session and weekly Plus 1, Pro 100 5, Pro 200 20; Claude session Pro 1, Max 5, Ultra 20. A pool with any unknown plan keeps equal weights. Fixes #13110 AI-assisted; verified with the tests and tools listed above.
| "ChatGPT Pro 200 Subscription": 20, | ||
| }; | ||
| // Claude's published plan multipliers describe the session allowance only. | ||
| const CLAUDE_SESSION_CAPACITY: Record<string, number> = { Pro: 1, Max: 5, Ultra: 20 }; |
There was a problem hiding this comment.
🟠 High src/usageLimits.ts:548
Claude subscriptions are never assigned their published session weights, so a pool with an exhausted Ultra account and an unused Pro account reports 50% remaining instead of 5%. account.plan contains labels such as Claude Ultra Subscription, but CLAUDE_SESSION_CAPACITY is keyed by bare names; use the emitted full labels as the keys.
| const CLAUDE_SESSION_CAPACITY: Record<string, number> = { Pro: 1, Max: 5, Ultra: 20 }; | |
| const CLAUDE_SESSION_CAPACITY: Record<string, number> = { | |
| "Claude Pro Subscription": 1, | |
| "Claude Max Subscription": 5, | |
| "Claude Ultra Subscription": 20, | |
| }; |
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @packages/shared/src/usageLimits.ts around line 548:
Claude subscriptions are never assigned their published session weights, so a pool with an exhausted Ultra account and an unused Pro account reports 50% remaining instead of 5%. `account.plan` contains labels such as `Claude Ultra Subscription`, but `CLAUDE_SESSION_CAPACITY` is keyed by bare names; use the emitted full labels as the keys.
ApprovabilityVerdict: Would Approve Macroscope's review found this PR approvable — Pooled usage displays now weight accounts by recognized plan capacity, including pace and reset contributions. The reported Claude-label mismatch remains subject to the separate correctness gate; the change otherwise affects informational displays rather than billing or enforced limits. Needs human approval because:
Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more. |
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Other scenariosAll 64 scenario measurements match All 64 scenario measurements
Baseline: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
|
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
…dotgg#35427) (cherry picked from commit 0b21a82)
Cause: poolWindows in packages/shared/src/usageLimits.ts averaged members' usedPercent, the pace inputs (used and elapsed share) and each reset's restoresPercent evenly. It ignored LimitAccount.plan, so a ChatGPT Pro 20x and a Plus counted the same. Fix: a new planCapacity(account, kind) looks up two small tables keyed on the plan labels the server already emits. Codex session and weekly windows: 'ChatGPT Plus Subscription' 1, 'ChatGPT Pro 100 Subscription' 5, 'ChatGPT Pro 200 Subscription' 20 (labels from codexPlanLabel). Claude session windows only: Pro 1, Max 5, Ultra 20 (from claudeSubscriptionLabel, where max5 maps to Max and max20 to Ultra; the session-only rule follows the closed #13675). If any member of a pooled window has an unknown plan, every member counts once, as before. Examples of unknown plans: the hub's generic 'Claude Subscription', Pro 500, Business, Enterprise, other drivers. Otherwise used percent, pace and restoresPercent are weighted by capacity over the total weight. With a used-up Pro 200 and an unused Plus, the pool shows 5% left and the Pro reset restores 95%. Only the shared helper changes, so the web, desktop and mobile Limits views and the mobile widget all get the corrected figures. No new regex or parser: the lookups are plain object reads. The repro test from factory/repro-13110 is kept and now passes.
Fixes #13110
Reproduction on main
Commit f03db4f (origin/main). Copied apps/web/test/fixtures/usage-limits-hub/hub.mjs to scratch and changed plan_type to come from each scenario account. Scenario: Codex account 'pro20x' (plan_type pro, which the server labels 'ChatGPT Pro 200 Subscription', i.e. 20x) at 100% session and weekly used, and Codex account 'plus' (plan_type plus) at 0% used. Ran T3CODE_DEV_SEED=0 vp run dev with empty CODEX_HOME and CLAUDE_CONFIG_DIR, paired the browser, and added the hub under Settings > Providers > Usage providers > Add hub (http://127.0.0.1:18517, label 'Team hub'). Opened Usage > Limits. The Codex Weekly row showed '50% left' and '↻ +50%', and the Session row also showed 50% / +50%. Clicking the Pro segment showed Plan 'ChatGPT Pro 200 Subscription', Left 0%, 'Restores +50% of pool'. Also added a unit test to packages/shared/src/usageLimits.test.ts ('weights pooled Codex quota and resets by each account's plan capacity'). It fails on main with remainingPercent 50 (expected 5), and the Pro reset restores 50 (expected 95).
Evidence
Reproduced in Chromium, 1280×800, light theme, against fresh databases on both commits. Add synthetic Team hub under Settings > Providers, pooling an exhausted ChatGPT Pro 20x account with an unused Plus account. Open Usage > Limits, then click the exhausted Pro segment.
The scenario failed on base and passed on head; scenarios:prove exited 0. Base displayed 50% remaining and a 50% Pro reset contribution. Head displayed 5% remaining and a 95% Pro reset contribution.
Scenario and synthetic hub driver
AI-assisted; verified with the tests and tools listed above.
Not shown:
Tests
vp test run packages/shared/src/usageLimits.test.ts -t 'plan capacity' with the fix stashed: 1 failed (expected 50 to be 5), so the bug reproduces. vp test run packages/shared/src/usageLimits.test.ts with the fix: 70/70 passed. vp run check:changed: all passed (format, lint, knip 1/2 and 2/2, typecheck of 35 packages, tests in 2 files with 72/72 passing). The pre-commit hook's fmt, lint and knip:check also passed.
Not in this change
AI-assisted; verified with the tests and tools listed above.